package com.avic.system.service.impl;

import com.avic.system.common.constant.LocalCacheConstant;
import com.avic.system.common.enums.UserTypeEnums;
import com.avic.system.common.util.AssertUtil;
import com.avic.system.common.util.ex.BizErrorCode;
import com.avic.system.common.util.ex.BizException;
import com.avic.system.dal.condition.PageQueryUserCondition;
import com.avic.system.dal.model.LoginLog;
import com.avic.system.dal.model.SystemPermission;
import com.avic.system.dal.model.SystemUser;
import com.avic.system.dal.model.vo.UserSystemMenu;
import com.avic.system.service.SystemUserService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.UUID;

/**
 * 系统用户serviceImpl
 *
 * @author: huangsheng
 * @date: 2017/10/19
 */
@Service("systemUserService")
@Slf4j
public class SystemUserServiceImpl extends SystemAbstractServiceImpl implements SystemUserService {

    /**
     * 分页获取系统用户
     *
     * @see SystemUserService#querySystemUserList(PageQueryUserCondition)
     */
    @Override
    public List<SystemUser> querySystemUserList(PageQueryUserCondition pageQueryUserCondition) {
        try {
            List<SystemUser> systemUsers = systemUserMapper.pageQueryUser(pageQueryUserCondition);
            return systemUsers;
        } catch (Exception e) {
            logger.error("分页获取系统用户查询数据库异常：{}", e.getMessage());
            throw new BizException(BizErrorCode.SYSTEM_ERROR, "分页获取系统用户查询数据库异常");
        }
    }

    /**
     * 分页查询系统用户数据总数
     *
     * @see SystemUserService#queryTotalRecords(PageQueryUserCondition)
     */
    @Override
    public int queryTotalRecords(PageQueryUserCondition pageQueryUserCondition) {

        return systemUserMapper.queryRecordsTotal(pageQueryUserCondition);
    }

    /**
     * 用户登入
     *
     * @see SystemUserService#queryUserForLogin(String, String, String)
     */
    @Override
    public SystemUser queryUserForLogin(String userLoginName, String password, String loginIp) {
        SystemUser systemUser = systemUserMapper.queryUserByLoginName(userLoginName);
        // 校验用户账号
        AssertUtil.isTrue(null != systemUser, BizErrorCode.USER_LOGIN_NAME_ERROR);
        // 校验用户状态
        AssertUtil.isTrue(systemUser.getUserState() == SystemUser.USER_STATE_NORMAL, BizErrorCode.USER_IS_DISABLE);
        // 校验用户密码
        AssertUtil.isTrue(StringUtils.equals(systemUser.getPassword(), password), BizErrorCode.LOGIN_PASSWORD_ERROR);
        try {
            if (LocalCacheConstant.LOGIN_USER_ID.containsKey(systemUser.getId())) {
                // 存在未退出的用户
                int loginId = LocalCacheConstant.LOGIN_USER_ID.get(systemUser.getId());
                loginLogMapper.updateLoginDuration(loginId);
            }

            LoginLog loginLog = new LoginLog(systemUser.getId(), systemUser.getCurrentLoginTime(), loginIp);
            loginLogMapper.insertLoginLog(loginLog);
            logger.info("登入日志ID = {}", loginLog.getId());

            logger.info("用户状态有效，更新用户登入信息, 当前登入IP = {}", loginIp);
            int successUpdateCount = systemUserMapper.updateLoginInfo(loginIp, systemUser.getId(), loginLog.getId());
            LocalCacheConstant.LOGIN_USER_ID.put(systemUser.getId(), loginLog.getId());
            logger.info("成功更新{}条记录", successUpdateCount);
        } catch (Exception e) {
            logger.error("更新用户登录信息异常：{}", e);
        }
        return systemUser;
    }

    /**
     * 创建用户
     *
     * @see SystemUserService#createUser(SystemUser)
     */
    @Override
    public String createUser(SystemUser systemUser) {
        int userLoginNameCount = systemUserMapper.checkUserLoginName(systemUser.getUserLoginName());
        logger.info("用户名在系统中存在 {} 条", userLoginNameCount);
        AssertUtil.isTrue(userLoginNameCount == 0, BizErrorCode.USER_LOGIN_NAME_IS_EXIST);

        try {
            SystemUser createSystemUser = new SystemUser();
            String userId = UUID.randomUUID().toString();
            logger.info("准备创建用户，ID = {}", userId);
            createSystemUser.setId(userId);
            createSystemUser.setUserLoginName(systemUser.getUserLoginName());
            createSystemUser.setUserName(systemUser.getUserName());
            createSystemUser.setUserDept(systemUser.getUserDept());
            createSystemUser.setUserPost(systemUser.getUserPost());
            createSystemUser.setPassword(systemUser.getPassword());
            int successInsertCount = systemUserMapper.insertUser(createSystemUser);
            logger.info("成功插入 {} 条数据", successInsertCount);
            return userId;
        } catch (Exception e) {
            logger.error("创建用户时异常：{}", e.getMessage());
            throw new BizException(BizErrorCode.SYSTEM_ERROR, "创建用户执行数据库异常");
        }
    }

    /**
     * 批量创建用户角色数据
     *
     * @see SystemUserService#batchCreateUserRole(List, String)
     */
    @Override
    public void batchCreateUserRole(List<String> roleIds, String userId) {
        try {
            if (null != roleIds && roleIds.size() > 0) {
                logger.info("新增用户{}的角色", userId);
                userRoleMapper.batchInsertUserRole(roleIds, userId);
            }
        } catch (Exception e) {
            logger.error("创建用户角色时异常：{}", e.getMessage());
        }
    }

    /**
     * 获取用户所拥有的所有角色id集合
     *
     * @see SystemUserService#getUserRoleIds(String)
     */
    @Override
    public List<String> getUserRoleIds(String userId) {

        logger.info("获取用户id为{}的角色数据", userId);
        return userRoleMapper.queryRoleIdsByUserId(userId);
    }

    /**
     * 获取用户信息
     *
     * @see SystemUserService#getUserByUserId(String)
     */
    @Override
    public SystemUser getUserByUserId(String userId) {
        logger.info("获取用户ID为 {} 的用户数据", userId);
        SystemUser systemUser = systemUserMapper.queryUserById(userId);
        AssertUtil.isTrue(null != systemUser, BizErrorCode.USER_IS_NOE_EXIST);
        return systemUser;
    }

    /**
     * 更新用户
     *
     * @see SystemUserService#updateUser(List, SystemUser)
     */
    @Override
    public void updateUser(List<String> roleIds, SystemUser systemUser) {
        SystemUser querySystemUser = systemUserMapper.queryUserById(systemUser.getId());
        AssertUtil.isTrue(null != systemUser, BizErrorCode.USER_IS_NOE_EXIST);

        // 校验登入名是否存在
        if (StringUtils.isNotBlank(systemUser.getUserLoginName())) {
            int userLoginNameCount = systemUserMapper.checkUserLoginName(systemUser.getUserLoginName());
            logger.info("修改的用户名：userLoginName = {}, 用户原用户名 = {}", systemUser.getUserLoginName(), querySystemUser.getUserLoginName());
            if (!StringUtils.equals(querySystemUser.getUserLoginName(), systemUser.getUserLoginName())) {
                AssertUtil.isTrue(userLoginNameCount == 0, BizErrorCode.USER_LOGIN_NAME_IS_EXIST);
            }
        }
        // 更新数据
        try {
            int successUpdateCount = systemUserMapper.updateSystemUser(systemUser);
            logger.info("成功更新 {} 条数据", successUpdateCount);
            //更新用户角色, 删除后在批量新增过去
            this.updateUserRole(roleIds, systemUser.getId());
        } catch (Exception e) {
            logger.error("更新用户时异常：{}", e);
            throw new BizException(BizErrorCode.SYSTEM_ERROR, "系统异常");
        }
    }

    @Override
    public void updateUser(SystemUser systemUser) {
        SystemUser querySystemUser = systemUserMapper.queryUserById(systemUser.getId());
        AssertUtil.isTrue(null != systemUser, BizErrorCode.USER_IS_NOE_EXIST);

        // 校验登入名是否存在
        if (StringUtils.isNotBlank(systemUser.getUserLoginName())) {
            int userLoginNameCount = systemUserMapper.checkUserLoginName(systemUser.getUserLoginName());
            logger.info("修改的用户名：userLoginName = {}, 用户原用户名 = {}", systemUser.getUserLoginName(), querySystemUser.getUserLoginName());
            if (!StringUtils.equals(querySystemUser.getUserLoginName(), systemUser.getUserLoginName())) {
                AssertUtil.isTrue(userLoginNameCount == 0, BizErrorCode.USER_LOGIN_NAME_IS_EXIST);
            }
        }
        try {
            int successUpdateCount = systemUserMapper.updateSystemUser(systemUser);
            logger.info("成功更新 {} 条数据", successUpdateCount);
        } catch (Exception e) {
            logger.error("更新用户时异常：{}", e);
            throw new BizException(BizErrorCode.SYSTEM_ERROR, "系统异常");
        }
    }

    /**
     * 更新用户角色, 删除后在批量新增过去
     *
     * @see SystemUserService#updateUserState(int, String)
     */
    private void updateUserRole(List<String> roleIds, String userId) {
        try {
            int successDeleteCount = userRoleMapper.deleteRoleByUserId(userId);
            logger.info("删除用户 {} 下的所有roleId, 成功删除 {} 条数据", userId, successDeleteCount);
        } catch (Exception e) {
            logger.error("删除用户 {} 下的roleId异常 {}", userId, e);
        }
        this.batchCreateUserRole(roleIds, userId);
    }

    /**
     * 修改用户状态，禁用or启用
     *
     * @see SystemUserService#updateUserState(int, String)
     */
    @Override
    public void updateUserState(int userState, String userId) {
        try {
            int successUpdateCount = systemUserMapper.updateSystemUserState(userState, userId);
            logger.info("成功更新 {} 条数据", successUpdateCount);
        } catch (Exception e) {
            logger.error("修改用户状态，禁用or启用时异常：{}", e);
            throw new BizException(BizErrorCode.SYSTEM_ERROR, "系统异常");
        }
    }

    /**
     * 根据用户信息查询菜单数据
     *
     * @see SystemUserService#getUserMenuData(String, String)
     */
    @Override
    public List<UserSystemMenu> getUserMenuData(String userLoginName, String userId) {
        try {
            if (StringUtils.equals(UserTypeEnums.ADMIN.getUserType(), userLoginName)) { // 如果是admin查询所有菜单数据
                logger.info("查询admin的菜单数据，所有菜单数据");
                List<UserSystemMenu> adminMenuList = userMenuPermissionMapper.queryAdminMenu();
                return adminMenuList;
            } else { // 如果是用户查询用户权限下拥有的菜单
                List<String> menuIds = userMenuPermissionMapper.queryUserMenuIds(userId);
                if (null != menuIds && menuIds.size() > 0) {
                    logger.info("根据用户权限查询出来拥有的菜单ID数量: {}", menuIds.size());
                    List<UserSystemMenu> userMenuList = userMenuPermissionMapper.queryUserSystemMenu(menuIds);
                    return userMenuList;
                }
            }
            return null;
        } catch (Exception e) {
            logger.error("根据用户信息查询菜单数据时异常：{}", e);
            throw new BizException(BizErrorCode.SYSTEM_ERROR, "查询用户菜单时发生异常");
        }
    }

    /**
     * 根据用户查询出用户拥有的权限codes，去重复
     *
     * @see SystemUserService#getUserPermission(String)
     */
    @Override
    public List<SystemPermission> getUserPermission(String userId) {

        return userMenuPermissionMapper.queryUserPermission(userId);
    }

    @Override
    public void changePassword(String oldPassword, String password, String userId) {
        SystemUser systemUser = systemUserMapper.queryUserPassword(userId);
        AssertUtil.isTrue(null != systemUser, BizErrorCode.PARAM_ERROR, "用户不存在");
        AssertUtil.isTrue(StringUtils.equals(oldPassword, systemUser.getPassword()), BizErrorCode.PARAM_ERROR, "你的原密码不正确");

        try {
            SystemUser updateSystemUser = new SystemUser();
            updateSystemUser.setModifyId(userId);
            updateSystemUser.setPassword(password);
            updateSystemUser.setId(userId);
            systemUserMapper.updateUserPassword(updateSystemUser);
        } catch (Exception e) {
            log.error("更新用户 {} 密码时,发生错误{}", userId, e.getMessage());
            throw new BizException(BizErrorCode.SYSTEM_ERROR);
        }
    }

    @Override
    public void resetPassword(String password, String userId) {
        try {
            SystemUser updateSystemUser = new SystemUser();
            updateSystemUser.setModifyId("1");
            updateSystemUser.setPassword(password);
            updateSystemUser.setId(userId);
            systemUserMapper.updateUserPassword(updateSystemUser);
        } catch (Exception e) {
            log.error("重置用户 {} 密码时,发生错误{}", userId, e.getMessage());
            throw new BizException(BizErrorCode.SYSTEM_ERROR);
        }
    }
}
